/*  This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License, or (at
    your option) any later version.
    For more details, see the GNU Lesser General Public License (www.fsf.org
    or the COPYING file somewhere in the package)
 */

#ifndef OSGI_BUNDLE_HH
#define OSGI_BUNDLE_HH

#include "OSGi.hh"

/*! @file OSGi/Bundle.hh
    @brief Class OSGi::Bundle header.
    @author @ref Guillaume_Terrissol
    @date 12th December 2009 - 11th April 2014
    @note This file is distributed under the LGPL license.
    Refer to the file COPYING (or http://www.fsf.org) for more information.
 */

#include <memory>
#include <iosfwd>
#include <vector>

#include "PImpl.hh"

namespace OSGi
{
//------------------------------------------------------------------------------
//                                    Bundle
//------------------------------------------------------------------------------

    /*! @brief The bundle itself.
        @version 0.7

        @todo Add bundle encryption
    */
    class OSGI_EXPORT Bundle : public std::enable_shared_from_this<Bundle>
    {
        OSGI_PROTECTED_CONSTRUCTOR()
    public:
        //! @name Pointers
        //@{
        using Ptr         = std::shared_ptr<Bundle>;                            //!< Pointer to bundle.
        using CPtr        = std::shared_ptr<const Bundle>;                      //!< Pointer to constant bundle.
        using ResourcePtr = std::shared_ptr<std::istream>;                      //!< Pointer to a bundle resource.
        using ContextPtr  = std::shared_ptr<Context>;                           //!< Pointer to context.
        using ContextCPtr = std::shared_ptr<const Context>;                     //!< Pointer to constant context.
        //@}
        friend class BundleFactory;                                             //!< For access to action methods.
        /*! @brief Pointer to bundle less-than.
            @version 0.5

            Allows to sort the bundles according to their dependencies.
         */
        struct Sorter
        {
            void    operator()(std::vector<Bundle::Ptr>& pResolved) const;      //!< Function operator.
        };
        //! @name Constructor & destructor
        //@{
                            Bundle(std::string pFilename,
                                   int         pId,
                                   ContextCPtr pContext,
                                   const Key&);                                 //!< Constructor.
virtual                     ~Bundle();                                          //!< Destructor.
        //@}
        //! @name Swaps
        //@{                                                    
        void                swap(Bundle& pThat);                                //!< Swap by reference.
        void                swap(Bundle::Ptr pThat);                            //!< Swap by [smart] pointer.
        //@}
        //! @name Information
        //@{
        std::string         name() const;                                       //!< Bundle name.
        int                 id() const;                                         //!< Bundle Id.
        Properties*         properties();                                       //!< Bundle properties.
        const Properties*   properties() const;                                 //!< Bundle constant properties.
        std::string         state() const;                                      //!< Bundle current state.
        std::string         version() const;                                    //!< Bundle version.
        ResourcePtr         resource(const std::string& pPath) const;           //!< Access to a bundle resource.
        //@}
        bool                act(const std::string& pName, ContextPtr pContext); //!< Action to change state.

    protected:
        //! @name States
        //@{
        void                setState(const std::string& pName);                 //!< Setting new state.
        void                setTemporaryState(const std::string& pName);        //!< Setting temporary state.
        //@}

    private:
        //! @name Actions
        //@{
        bool                start(ContextPtr pContext);                         //!< Starting bundle.
        bool                stop(ContextPtr pContext);                          //!< Stopping bundle.
        bool                uninstall(ContextPtr pContext);                     //!< Uninstalling bundle.
        bool                tryResolve(ContextPtr pContext);                    //!< Resolving bundle.
        //@}
        OSGI_PIMPL()
    };

    extern const std::string    kBndlExt;                                       //!< Bundle file extension.
}

#endif  // OSGI_BUNDLE_HH
